#pragma once
#include <iostream>
#include <sys/select.h>
#include <sys/epoll.h>
#include "Log.hpp"
#include "socket.hpp"

using namespace socket_ns;
static const int N = sizeof(fd_set) * 8;
static const int defaultfd = -1;
static const int gnum = 64;
class EpollServer
{
public:
    EpollServer(int port)
        : _port(port), _listensocket(std::make_shared<TcpSocket>())
    {
        InetAddr local(port);
        _listensocket->BuildServerSocket(local);
        // 创建epoll模型
        _epfd = epoll_create(128);
        // 将listensock设置进去
        struct epoll_event epo;
        epo.events = EPOLLIN;
        epo.data.fd = _listensocket->SockFd();
        int n = epoll_ctl(_epfd, EPOLL_CTL_ADD, _listensocket->SockFd(), &epo);
        if (n < 0)
        {
            Log(FATAL, "epoll_ctl listensockfd fail...");
            exit(5);
        }
        Log(DEBUG, "epoll_ctl listensockfd success...");
    }
    // listensockfd已经就绪
    void AcceptClient()
    {
        InetAddr client;
        int sockfd = _listensocket->AcceptSocket(&client);
        if (sockfd < 0)
        {
            Log(DEBUG, "accept fail...");
        }
        struct epoll_event epo;
        epo.events = EPOLLIN;
        epo.data.fd = sockfd;
        int n = epoll_ctl(_epfd, EPOLL_CTL_ADD, sockfd, &epo);
        if (n < 0)
        {
            Log(FATAL, "epoll_ctl sockfd fail...%d", sockfd);
            exit(5);
        }
        Log(DEBUG, "epoll_ctl sockfd success...%d", sockfd);
    }
    // readfd就绪
    void ServiceEcho(int pos)
    {

        char recvbuffer[1024];
        int sockfd = _events->data.fd;
        int n = recv(sockfd, recvbuffer, sizeof(recvbuffer)-1, 0);
        // std::cout << "recv end" << std::endl;
        if (n > 0)
        {
            recvbuffer[n] = 0;
            std::cout << recvbuffer << std::endl;
            std::string echostring = "Echo Server#";
            echostring += recvbuffer;
            send(sockfd, echostring.c_str(), echostring.size(), 0);
        }
        else if (n == 0)
        {
            Log(ERROR, "%d connect alrady close!", sockfd);
            close(sockfd);
            sockfd = defaultfd;
        }
        else
        {
            Log(ERROR, "%d recv error!", sockfd);
            close(sockfd);
            sockfd = defaultfd;
        }
    }
    void HanderEpoll(int n)
    {
        for (int i = 0; i < n; i++)
        {
            if (_events->events == EPOLLIN)
            {
                if (_events->data.fd == _listensocket->SockFd())
                {
                    AcceptClient();
                }
                else
                {
                    ServiceEcho(i);
                }
            }
        }
    }

    void start()
    {
        while (true)
        {
            sleep(1);
            int timeout = 1000;
            int n = epoll_wait(_epfd, _events, gnum, -1);
            switch (n)
            {
            case 0:
                Log(DEBUG, "epoll_wait 为0...");
                break;
            case -1:
                Log(DEBUG, "epoll_wait fail...");
                break;
            default: // 必然有就绪的fd
                // Log(DEBUG, "enter hander");
                HanderEpoll(n);
                break;
            }
        }
    }
    ~EpollServer()
    {
    }

private:
    int _port;
    socket_ptr _listensocket;
    int _epfd;
    struct epoll_event _events[gnum];
};